package com.jasonzqshen.ifm.utils;

import java.util.Random;

public class Identifier {

    private static Random random = new Random(System.currentTimeMillis());

    private static final int RANDOM_MAX = 99999999;

    private static final int RANDOM_MIN = 0;

    private static final char SPLIT_SYMBOL = '_';

    private static final int IDENTITY_SLICE_COUNT = 4;

    private static final String INITIAL_STRING = "id";

    private String idString;

    /**
     * Construct Identifier
     * 
     * @throws InvalidIdentifierException
     */
    public Identifier() {
        StringBuilder strBuilder = new StringBuilder();
        int[] num = new int[IDENTITY_SLICE_COUNT];
        for (int i = 0; i != IDENTITY_SLICE_COUNT; ++i) {
            num[i] = random.nextInt(RANDOM_MAX);
        }
        for (int n : num) {
            String str = this.turnNum2Str(n);
            while (str == null) {
                int tmpNum = random.nextInt(RANDOM_MAX);
                str = this.turnNum2Str(tmpNum);
            }

            strBuilder.append(String.format("%c%s", SPLIT_SYMBOL, str));
        }
        idString = String.format("%s%s", INITIAL_STRING, strBuilder.toString());
    }

    /**
     * Construct Tree Node Identify
     * 
     * @param idStr
     * @throws InvalidIdentifierException
     */
    public Identifier(String idStr) throws InvalidIdentifierException {
        this.idString = idStr;
        if (this.validIdentifier() == false) {
            throw new InvalidIdentifierException(String.format(
                    "Invalid identifier string %s", idStr));
        }
    }

    /**
     * Override toString
     */
    @Override
    public String toString() {
        return this.idString;
    }

    /**
     * Clone
     */
    @Override
    public Object clone() {
        Identifier id = null;
        try {
            id = new Identifier(this.idString);
        } catch (InvalidIdentifierException e) {
            return null;
        }
        return id;
    }

    @Override
    public boolean equals(Object obj) {
        if (!this.getClass().equals(obj.getClass())) {
            return false;
        }
        Identifier tmpId = (Identifier) obj;
        return this.idString.equals(tmpId.idString);
    }

    @Override
    public int hashCode() {
        return this.idString.hashCode();
    }

    /**
     * Number should be between RANDOM_MIN and RANDOM_MAX
     * 
     * @param number
     * @return
     */
    private String turnNum2Str(int number) {
        if (number < RANDOM_MIN || number > RANDOM_MAX) {
            return null;
        }
        StringBuilder strBuilder = new StringBuilder();
        String numStr = ((Integer) number).toString();
        int len = numStr.length();
        for (int i = 0; i != 8 - len; ++i) {
            strBuilder.append('0');
        }
        strBuilder.append(numStr);
        return strBuilder.toString();
    }

    /**
     * valid identifier
     * 
     * @return
     */
    private boolean validIdentifier() {
        if (idString == null) {
            return false;
        }
        final int LEN = 9 * IDENTITY_SLICE_COUNT + INITIAL_STRING.length();
        if (this.idString.length() != LEN) {
            return false;
        }

        String words[] = idString.split("_");
        int len = words.length;
        if (len != IDENTITY_SLICE_COUNT + 1) {
            return false;
        }

        if (!words[0].equalsIgnoreCase(INITIAL_STRING)) {
            return false;
        }

        for (int i = 1; i < len; ++i) {
            try {
                Integer.parseInt(words[i]);
            } catch (NumberFormatException e) {
                return false;
            }
        }

        return true;
    }
}
